﻿using System.Collections;
using System.Text;
using OnDash.Windowing.GraphicsLibraryFramework.Enums;

namespace OnDash.Windowing.GraphicsLibraryFramework.Inputs;

public class KeyboardState
{
    private readonly BitArray _keys = new((int)Keys.LastKey + 1);
    private readonly BitArray _keysPrevious = new((int)Keys.LastKey + 1);

    private KeyboardState(KeyboardState source)
    {
        _keys = (BitArray)source._keys.Clone();
        _keysPrevious = (BitArray)source._keysPrevious.Clone();
    }

    internal KeyboardState()
    {
    }

    public bool this[Keys key]
    {
        get => IsKeyDown(key);
        private set => SetKeyState(key, value);
    }

    public bool IsAnyKeyDown
    {
        get
        {
            for (var i = 0; i < _keys.Length; ++i)
                if (_keys[i])
                    return true;

            return false;
        }
    }

    internal void SetKeyState(Keys key, bool down)
    {
        _keys[(int)key] = down;
    }

    public override string ToString()
    {
        var builder = new StringBuilder();
        builder.Append('{');
        var first = true;

        for (Keys key = 0; key <= Keys.LastKey; key++)
        {
            if (!IsKeyDown(key)) continue;
            builder.Append($"{key}{(!first ? ", " : string.Empty)}");
            first = false;
        }

        builder.Append('}');

        return builder.ToString();
    }

    internal void Update()
    {
        _keysPrevious.SetAll(false);
        _keysPrevious.Or(_keys);
    }

    public bool IsKeyDown(Keys key) =>
        _keys[(int)key];

    public bool WasKeyDown(Keys key) =>
        _keysPrevious[(int)key];

    public bool IsKeyPressed(Keys key) =>
        _keys[(int)key] && !_keysPrevious[(int)key];

    public bool IsKeyReleased(Keys key) =>
        !_keys[(int)key] && _keysPrevious[(int)key];

    public KeyboardState GetSnapshot() => new(this);
}